package com.zhixiang.core.util;

import com.fr.base.ArrayUtils;
import org.hibernate.SessionFactory;
import org.hibernate.metadata.ClassMetadata;

import javax.persistence.Id;
import javax.persistence.IdClass;
import java.lang.reflect.Field;

public class ReflectUtils
{

    /**
     * 取得对象的主键名. 仅仅适合只有标记一个@ID情况
     */
    public static String getIdName(SessionFactory sessionFactory,Class clazz) {
        ClassMetadata meta = sessionFactory.getClassMetadata(clazz);
        return meta.getIdentifierPropertyName();
    }
    
    /**
     * 取得对象的主键名.
     */
    public static String[] getIdNames(Class clazz) {
        /*ClassMetadata meta = getSessionFactory().getClassMetadata(entityClass);
        String[] names = {};
        try {
            names = (String[]) BeanUtils.invokePrivateMethod(meta, "getIdentifierColumnNames");
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return names;
        */
        String[] idNames = {};
        Field[] fields = Utils.getDeclaredFields(clazz);
        for (Field field : fields){
            try {
                if(field.isAnnotationPresent(Id.class)){
                    Id id = field.getAnnotation(Id.class);
                    if (id!=null){
                        idNames=(String[]) ArrayUtils.add(idNames, field.getName());
                    }
                }
            }catch (SecurityException e) {
                e.printStackTrace();
            }                           
        }       
        return idNames;
    }
    

    /**
     * 取得对象的主键名.包含@Id和@EmbeddedId的情况
     */
    public static String[] getIdNames(Object entity) {
        Class clazz = entity.getClass();
        return getIdNames(clazz);
    }
    
    /**
     * 判断fieldName是否主键.
     */
    public static boolean isIdName(SessionFactory sessionFactory,Class clazz,String fieldName) {
        boolean isIdName = false;
        if (clazz.getAnnotation(IdClass.class)==null){
            String name=getIdName(sessionFactory,clazz);
            if (fieldName.equals(name)) {
                isIdName = true;
            }
        }else{
            String[] names = getIdNames(clazz);
            for (String name : names) {
                if (fieldName.equals(name)) {
                    isIdName = true;
                    break;
                }
            }
        }       
        return isIdName;
    }
    /**   
     * 循环向上转型, 获取对象的 DeclaredField   
     * @param object : 子类对象   
     * @param fieldName : 父类中的属性名   
     * @return 父类中的属性对象   
     * add by gt
     */          
    public static Field getDeclaredField(Object object, String fieldName){    
        Field field = null ;              
        Class<?> clazz = object.getClass() ;              
        for(; clazz != Object.class ; clazz = clazz.getSuperclass()) {    
            try {    
                field = clazz.getDeclaredField(fieldName) ;    
                return field ;    
            } catch (Exception e) {    
                //这里甚么都不要做！并且这里的异常必须这样写，不能抛出去。    
                //如果这里的异常打印或者往外抛，则就不会执行clazz = clazz.getSuperclass(),最后就不会进入到父类中了                      
            }     
        }          
        return field;    
    } 
}
